#include <cmath>

#include <algorithm>
#include <fstream>
#include <tuple>
#include <unordered_set>
#include <vector>
using namespace std;

struct Car
{
    int d, v, a;
    int leave_pos;
    int over_speed_start;
};

constexpr pair<int, int> compute_info(const Car& car, int V, int L)
{
    // compute where the car leave the road
    int leave_pos = L, over_speed_start = L + 1;
    if (car.a < 0) {
        leave_pos = 
            car.d + (V * V - car.v * car.v + 2 * car.a + 1) / (2 * car.a) - 1;
    }

    if (car.a > 0) {
        // compute where the car start to be over-speed
        over_speed_start = car.d + (V * V - car.v * car.v) / (2 * car.a) + 1;
    } else if (car.v > V) {
        over_speed_start = car.d;
    }

    return {leave_pos, over_speed_start};
}

int main()
{
    ifstream input("detect.in");
    ofstream output("detect.out");
    int t;
    input >> t;
    while (t--) {
        int n, m, L, V;
        input >> n >> m >> L >> V;
        vector<Car> cars(n);
        for (auto& car : cars) {
            input >> car.d >> car.v >> car.a;
            tie(car.leave_pos, car.over_speed_start) = compute_info(car, V, L);
        }

        vector<int> pos(m);
        for (auto& e : pos) {
            input >> e;
        }

        // find the detected cars
        vector<int> detected_cars;
        detected_cars.reserve(cars.size());
        for (int i = 0; i < cars.size(); ++i) {
            auto iter =
                lower_bound(pos.begin(), pos.end(), cars[i].over_speed_start);
            if (iter != pos.end() && *iter <= cars[i].leave_pos) {
                detected_cars.push_back(i);
            }
        }

        // remove some detectors
        auto compare = [&cars](int a, int b) {
            const auto& left = cars[a], right = cars[b];
            return left.leave_pos < right.leave_pos ||
                (left.leave_pos == right.leave_pos &&
                left.over_speed_start < right.over_speed_start);
        };
        sort(detected_cars.begin(), detected_cars.end(), compare);

        vector<int> neccessary_detectors;
        neccessary_detectors.reserve(pos.size());
        unordered_set<int> covered_cars;
        for (int i = 0; i < detected_cars.size(); ++i) {
            if (covered_cars.count(detected_cars[i]) == 0) {
                auto iter = upper_bound(
                    pos.begin(),
                    pos.end(),
                    cars[detected_cars[i]].leave_pos
                );
                if (iter != pos.begin()) {
                    --iter;
                    neccessary_detectors.push_back(*iter);
                    for (int j = i; j < detected_cars.size() &&
                        cars[detected_cars[j]].over_speed_start <= *iter;
                        ++j) {
                        covered_cars.insert(detected_cars[j]);
                    }
                }
            }
        }

        output << detected_cars.size() << ' '
            << pos.size() - neccessary_detectors.size() << '\n';
    }

    return 0;
}